/*******************************************************************************
 * ***** BEGIN LICENSE BLOCK *****
 *
 * This file is part of CCValidator.
 * Copyright 2009 Corlatti (http://www.corlatti.com.ar/)
 *
 * CCValidator is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * CCValidator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * ***** END LICENSE BLOCK *****
 *
 * $Id: CCValidator.js 16 2009-03-29 07:59:32Z corlatti $
 * 
 * This is the core main file.
 * 
 *******************************************************************************/
/* configuration */
//here you can set your own validation rules extending an existing one
CCValidator.prototype._RULES = new Array('Required', 'Numeric', 'Integer', 'Decimal', 'Min', 
											'Max', 'Alpha', 'Alphanumeric', 'Dateformat', 
											'Mail', 'Ip', 'Url');
CCValidator.prototype._RULES_ATTRIBUTE = 'validar';
CCValidator.prototype._FIELD_DESCRIPTION = 'title';
//action when validation fails
CCValidator.prototype._FAILED_BG_COLOR = '#FF9999';
CCValidator.prototype._FAILED_INFO = true;
CCValidator.prototype._FAILED_ALERT = false;

/* below this line: THE CORE ;) */
CCValidator.prototype._form;
CCValidationRule.prototype._validationResult;
CCValidationRule.prototype.validationMessage;

function CCValidator(form) {
	try {
		this._validationMessage = 'Algunos campos del formulario contienen datos erroneos, por favor corrijalos e intente nuevamente.\n\nDetalle de validacion:';
		this._validationResult = true;
		this._form = form;
		this.validate();
	} catch(e) {
		alert('Error en el motor de validacion: ' + e);
	}
}

CCValidator.prototype.validate = function(){
	var result = false;
	try {
		result = this._applyRules();
		if(!result){
			if(this._FAILED_ALERT)
				alert(this._validationMessage);
		}
	} catch(e) {
		throw e;
	}
	return result;
}

CCValidator.prototype._getDescription = function(obj){
	var result = '';
	try {
		var initialDescription = obj.name;
		//alert(obj.getAttribute(this._FIELD_DESCRIPTION));
		if((obj.getAttribute(this._FIELD_DESCRIPTION) != undefined) &&
			(obj.getAttribute(this._FIELD_DESCRIPTION) != '')){
			result = obj.getAttribute(this._FIELD_DESCRIPTION);
		} else {
			result = initialDescription;
		}
	} catch(e){
		throw e;
	}
	return result;
}

CCValidator.prototype._applyRules = function(){
	try {
		var frm = this._form;
		
		for(var i=0; i < frm.elements.length; i++){
			var obj = frm.elements[i];
			var validationsToPerform = this._rulesFinder(obj);
			if(validationsToPerform != null){
				var msg = '\n\t . ' + this._getDescription(obj) + ': ';
				var internalResult = true;
				this._changeBgColor(obj, '');
				this._removeInfoBoxes(obj);
				for(var j=0; j < validationsToPerform.length; j++){
					var rule = validationsToPerform[j].split('=');
					var execute = 'new ' + rule[0].trim().capitalize() + '(obj.id, obj.value,validationsToPerform[j])';
					var result = eval(execute);
					if(!result[0]){
						this._validationResult = false;
						if(!internalResult) result[1] = ' y ' + result[1];
						internalResult = false;
						msg = this._internalMsg(msg, result[1]);
					}
				}
				if(!internalResult){
					this._onFailAction(obj, msg);
				}
			}
		}
	} catch(e) {
		throw e;
	}
	return this._validationResult;
}

CCValidator.prototype._addMsg = function(msg){
	this._validationMessage += msg;
}

//se agrega para manejar la repeticion del "Y" o "and", segun sea el idioma,
//cuando una validacion tiene que cumplir varias reglas
CCValidator.prototype._internalMsg = function(msg, newMsg){
	var resultado = "";
	try {
		if(msg.substr(msg.length - 1).trim() == '.'){
			resultado = msg + ' ' + newMsg.trim().substr(1); 
		} else {
			resultado = msg + ' ' + newMsg.trim();
		}
	} catch(e){
		throw e;
	}
	return resultado;
}

CCValidator.prototype._onFailAction = function(obj, msg){
	try {
		this._addMsg(msg);
		if(this._FAILED_BG_COLOR != ''){
			this._changeBgColor(obj, this._FAILED_BG_COLOR);
		}
		if(this._FAILED_INFO){
			this._drawInfo(obj, msg);
		}
	} catch(e){
		throw e;
	}
}

CCValidator.prototype._changeBgColor = function(obj, color){
	obj.style.backgroundColor = color;
}

CCValidator.prototype._drawInfo = function(obj, msg){
	try {
		var infoBox = document.createElement('span');
		infoBox.setAttribute('id','validationError-' + obj.id);
		infoBox.setAttribute('class', 'validationError');
		var info = document.createTextNode(msg);
		infoBox.appendChild(info);
		obj.parentNode.appendChild(infoBox);
	} catch(e){
		throw e;
	}
}

CCValidator.prototype._removeInfoBoxes = function(obj){
	try {
		var id = obj.id;
		var info = document.getElementById('validationError-' + id);
		if(info != null)
			info.parentNode.removeChild(info);
	} catch(e){
		throw e;
	}
}

CCValidator.prototype._rulesFinder = function(obj){
	var result = null;
	try {
		var validationsToPerform = obj.getAttribute(this._RULES_ATTRIBUTE);
		if((validationsToPerform != null) && (validationsToPerform.trim() != '')){
			var validationRules = validationsToPerform.split(',');
			result = this._rulesValidator(validationRules); 
		}
	} catch(e){
		throw e;
	}
	return result;
}

CCValidator.prototype._rulesValidator = function(rules){
	var result = new Array();
	try {
		var j=0;
		for(var i=0; i<rules.length; i++){
			var tmp = rules[i].split('=');
			if(tmp[0].isIn(this._RULES)){
				result[j] = rules[i];
				j++;
			}
		}
		if(rules.length > result.length){
			throw 'Invalid rules: ' + rules.join(', ');
		}
	} catch(e){
		throw e;
	}
	return result;
}


